package com.wbl.train.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wbl.train.business.service.TrainSeatService;
import com.wbl.train.business.service.TrainStationService;
import com.wbl.train.common.business.dto.DailyTrainSeatDto;
import com.wbl.train.common.business.entity.*;
import com.wbl.train.business.mapper.DailyTrainSeatMapper;
import com.wbl.train.business.service.DailyTrainSeatService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wbl.train.common.exception.ApplicationException;
import com.wbl.train.common.page.PageVo;
import com.wbl.train.common.result.ResultCode;
import com.wbl.train.common.utils.SnowUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 每日座位 服务实现类
 * @author 王博纶
 * @since 2024-02-11
 */
@AllArgsConstructor
@Slf4j
@Service
public class DailyTrainSeatServiceImpl extends ServiceImpl<DailyTrainSeatMapper, DailyTrainSeatEntity> implements DailyTrainSeatService {

    private TrainSeatService trainSeatService;
    private TrainStationService trainStationService;

    @Override
    public PageVo<DailyTrainSeatEntity> queryTrainSeat(DailyTrainSeatDto dailyTrainSeatDto) {
        // 获取分页所需要的参数
        int page = dailyTrainSeatDto.getPage();
        int limit = dailyTrainSeatDto.getLimit();

        LambdaQueryWrapper<DailyTrainSeatEntity> dailyTrainSeatWrapper = new LambdaQueryWrapper<DailyTrainSeatEntity>()
                .orderByDesc(DailyTrainSeatEntity::getDate) // 按照 date 降序排序
                .orderByAsc(DailyTrainSeatEntity::getTrainCode) // 按照 trainCode 升序排序
                .orderByAsc(DailyTrainSeatEntity::getCarriageIndex) // 按照carriageIndex 车厢序号 升序排序
                .orderByAsc(DailyTrainSeatEntity::getCarriageSeatIndex) // 按照carriageSeatIndex 车厢座位号 升序排序
                // 根据date进行过滤，有值就过滤，没有值不拼接条件
                .eq(ObjectUtil.isNotEmpty(dailyTrainSeatDto.getDate()),DailyTrainSeatEntity::getDate,dailyTrainSeatDto.getDate())
                // 根据trainCode进行过滤，有值就过滤，没有值不拼接条件
                .eq(ObjectUtil.isNotEmpty(dailyTrainSeatDto.getTrainCode()),DailyTrainSeatEntity::getTrainCode,dailyTrainSeatDto.getTrainCode());
        //创建分页对象
        IPage<DailyTrainSeatEntity> dailyTrainSeatPage = new Page<>(page,limit);
        //调用分页方法
        IPage<DailyTrainSeatEntity> dailyTrainSeatPageData = page(dailyTrainSeatPage,dailyTrainSeatWrapper);
        // 获取查询出来的数据集合
        List<DailyTrainSeatEntity> records = dailyTrainSeatPageData.getRecords();
        // 将数据塞到PageVo类中并返回出去
        return new PageVo<DailyTrainSeatEntity>()
                .setDataList(records)
                .setPageSize(limit).setCurrentPage(page)
                .setTotal((int) dailyTrainSeatPageData.getTotal())
                .setPages((int) dailyTrainSeatPageData.getPages());
    }

    @Override
    public boolean insertAndUpdateTrain(DailyTrainSeatEntity dailyTrainSeat) {
        // 获取当前的时间 --- 用于创建和修改的时候的时间填充
        DateTime now = DateTime.now();
        // 设置火车车厢座位的修改时间
        dailyTrainSeat.setUpdateTime(now);
        // 判断Id是否为空
        if(ObjectUtil.isNotNull(dailyTrainSeat.getId())){
            // 根据id查询火车车厢座位信息
            DailyTrainSeatEntity dailyTrainSeatEntity = this.getById(dailyTrainSeat.getId());
            // 当前id对应的无火车车厢座位信息
            if(ObjectUtil.isNull(dailyTrainSeatEntity)){
                throw new ApplicationException(ResultCode.DATA_NOT_EXIST,"当前火车车厢座位不存在");
            }
            // 更新火车车厢座位信息
            return this.updateById(dailyTrainSeat);
        }
        // 给新增的火车车厢座位设置Id，创建时间和修改时间
        dailyTrainSeat.setId(SnowUtil.getSnowflakeNextId())
                .setCreateTime(now);
        // 新增火车车厢座位
        return this.save(dailyTrainSeat);
    }

    @Transactional
    public void genDailySeat(LocalDate date, String trainCode, Date now) {
        log.info("生成日期【{}】车次【{}】的座位信息开始",date,trainCode);
        ArrayList<DailyTrainSeatEntity> dailyTrainSeatList = new ArrayList<>();
        // 删除某日某车次的车站信息
        LambdaUpdateWrapper<DailyTrainSeatEntity> deleteWrapper = new LambdaUpdateWrapper<DailyTrainSeatEntity>()
                .eq(DailyTrainSeatEntity::getTrainCode, trainCode)
                .eq(DailyTrainSeatEntity::getDate, date);
        this.remove(deleteWrapper);

        // 查询车站信息
        List<TrainStationEntity> trainStations = trainStationService.selectByTrainCode(trainCode);
        // 构造座位的sell信息
        String sell = StrUtil.fillBefore("",'0',trainStations.size()-1);
        // 查出某车次的所有的车厢信息
        List<TrainSeatEntity> trainSeats = trainSeatService.selectByTrainCode(trainCode);
        if(CollUtil.isEmpty(trainSeats)){
            log.error("没有座位基础数据，生成该车次座位信息结束");
            throw new ApplicationException(ResultCode.DATA_NOT_EXIST,"没有座位基础数据，生成该车次座位信息结束");
        }

        for (TrainSeatEntity trainSeat : trainSeats) {
            // 创建并添加 每日车次 信息
            dailyTrainSeatList.add(BeanUtil.copyProperties(trainSeat, DailyTrainSeatEntity.class)
                    .setId(SnowUtil.getSnowflakeNextId())
                    .setDate(date)
                    .setSell(sell)
                    .setCreateTime(now)
                    .setUpdateTime(now));
        }
        this.saveBatch(dailyTrainSeatList);
        log.info("生成日期【{}】车次【{}】的座位信息结束",date,trainCode);
    }

    public int countSeat(LocalDate date, String trainCode, String seatType){
        LambdaQueryWrapper<DailyTrainSeatEntity> countWrapper = new LambdaQueryWrapper<DailyTrainSeatEntity>()
                .eq(DailyTrainSeatEntity::getDate,date)
                .eq(DailyTrainSeatEntity::getTrainCode,trainCode)
                .eq(ObjectUtil.isNotEmpty(seatType),DailyTrainSeatEntity::getSeatType,seatType);
        int count = Math.toIntExact(this.count(countWrapper));
        // 对返回的数量进行优化，没有对应的座位信息返回 -1 表示当前座位类型没有进行售卖
        return count == 0 ? -1 : count;
    }

    @Override
    public List<DailyTrainSeatEntity> selectByCarriage(LocalDate date, String trainCode, Integer index) {
        LambdaQueryWrapper<DailyTrainSeatEntity> wrapper = new LambdaQueryWrapper<DailyTrainSeatEntity>()
                .orderByAsc(DailyTrainSeatEntity::getCarriageSeatIndex) // 按照carriageSeatIndex 车厢座位号 升序排序
                .eq(DailyTrainSeatEntity::getDate,date)
                .eq(DailyTrainSeatEntity::getTrainCode,trainCode)
                .eq(DailyTrainSeatEntity::getCarriageIndex,index);
        return this.list(wrapper);
    }
}
